Secure Coding Summary and Practices
· 7 min read
Secure Coding Practices
SQL Injection
SQL Injection(주입 혹은 삽입)은 데이터베이스와의 연동하기 위한SQL문을 사용할때, 사용자 입력값에 대한 검증을 하지 않고 쿼리문을 생성하는 과정에서 발생한다. 공격자는 입력 값으로 예상 되는 실행 SQL문을 예측하여 입력 값으로 해당 SQL문을 조작하여 공격을 시도하게 된다. SQL Injection은 DBMS의 종류에 상관없이 취약점이 노출 될 수 있다.
Examples
예를 들어, 다음과 같이 사용자 입력 항목과 사용자 정보를 조회하는 애플리케이션에서 실행되는 SQL문이 있다고 할 경우, 공격자는 다음과 같은 입력 항목으로 작성된 쿼리문이 아닌 조작된 쿼리문을 실행할 수 있다.
'' or ='' and password='' or ='''' or 1=1; --'' or 1=1 --' or 'a' = 'a') or ('a' = 'a+ or 1=1 --
위의 입력 가능 항목 외에도, 예외를 발생 시킬 수 있는 값을 입력한 후, 발생되는 예외의 내용을 보고 SQL injection에 대한 취약점 여부를 판단할 수 있다. 따라서 발생 가능한 예외에 대한 적절한 처리가 필요하다.
입력 항목
ID: <input type=-"text" name="id" />
Password: <input type=-"password" name="password" />
Codes with SQL
String sql = "select * from member where id ='"+id+"' and password='"+password+"'";
필터링 해야하는 특수문자들
' " # - ( ) ; @ = * / +
필터링 해야하는 구문들
- union
- select
- insert
- drop
- update
- from
- where
- join
- substr (oracle)
- substring (ms-sql)
- user_tables (oracle)
- sysobjects (ms-sql)
- table_schema (mysql)
- declare (ms-sql)
- information_schema (mysql)
- user_table_columns (oracle)
처리 방법
SQL injection은 부당한 입력값으로 실행될 SQL문의 구조를 변경하는 공격이므로, 입력 값에 따라 실행될 SQL의 구조가 변경되지 않도록 해야 한다.
JDBC API 사용
최대한 PreparedStatement를 사용하여 외부에서 입력된 값을 바인딩해 사용해서, SQL의 구조가 바뀌지 않도록 한다.
String sql = "select * from member where id ='?' and password='?';
PreparedStatement pstmt = connection.prepareStatement(sql);
pstmt.setString(1, userId);
pstmt.setString(2, password);
...
MyBatis 사용
MyBatis와 같은 SQL Mapping framework을 사용하면 SQL injection 공격에 안전할 것이라고 생각되지만, MyBatis를 사용할때도 다음과 같은 사항에 유의해야 한다.
